import configparser
import threading

from .u_crypto import UCrypto

_WRITE_LOCK = threading.Lock()


class UConfig:
    _config = dict()

    @classmethod
    def get(cls, config_file: str, refresh=False):
        """
        从配置文件中读取配置,初始化 config, 非系统配置文件实时解析并返回，如果是系统配置文件会做缓存
        :param refresh: 强制重新读取配置标识
        :param config_file 配置文件路径，默认是系统配置文件
        :return:
        """
        if not cls._config.get(config_file, None) or refresh:
            cls._config[config_file] = get_config(config_file)
        return cls._config.get(config_file, dict())

    @classmethod
    def get_section_config(cls, config_file: str, section_name: str, refresh=False):
        """
        获取制定的子配置
        :param section_name:
        :param refresh: 强制重新读取配置标识
        :param config_file 配置文件路径
        :return:
        """
        config = cls.get(refresh=refresh, config_file=config_file)
        return config.get(section_name, dict())

    @classmethod
    def get_config_value(cls, config_file: str, section_name: str, option_name: str, crypto_mode="", refresh=False):
        """
        获取制定的子配置
        :param section_name:
        :param option_name:
        :param crypto_mode: 加密方式，默认不加密
        :param refresh: 强制重新读取配置标识
        :param config_file 配置文件路径，默认是系统配置文件
        :return:
        """
        sec_config = cls.get_section_config(section_name=section_name, refresh=refresh, config_file=config_file)
        value = sec_config.get(option_name)
        return UCrypto.decrypt(value, cipher_encoding="base64", encrypt_mode=crypto_mode)

    @classmethod
    def set_config_value(cls, config_file: str, section_name: str, option_name: str, option_value, crypto_mode=""):
        """
        获取制定的子配置
        :param section_name:
        :param option_name:
        :param option_value:
        :param crypto_mode: 加密方式，默认不加密
        :param config_file 配置文件路径，默认是系统配置文件
        :return:
        """
        with _WRITE_LOCK:
            config = get_origin_config(config_file)

            if section_name not in config.sections():
                config.add_section(section_name)

            write_value = UCrypto.encrypt(option_value, cipher_encoding="base64", encrypt_mode=crypto_mode)

            config.set(section_name, option_name, write_value)

            with open(config_file, "w") as f:
                config.write(f)


def parse_config(config_file: str):
    """
    从ini格式配置文件中获取配置信息
    :param config_file: 配置文件路径
    :return:
    """
    if not config_file:
        raise ValueError("Arg: config_file is empty when call func: parse_config")
    _config = dict()

    config_parser = configparser.ConfigParser()
    config_parser.read(config_file, encoding='utf-8')
    for option_ in config_parser.sections():
        option_config = dict()
        for key in config_parser.options(option_):
            value = config_parser.get(option_, key)
            option_config[key] = value
        _config[option_] = option_config

    return _config


def get_config(config_file: str = "", option: str = ""):
    """
    从ini格式配置文件中获取配置信息
    :return:
    """
    config = parse_config(config_file)

    if option:
        return config.get(option, {})
    else:
        return config


def get_origin_config(config_file: str = "") -> configparser.ConfigParser:
    """
    从ini格式配置文件中获取配置信息
    :return:
    """
    config_parser = configparser.ConfigParser()
    config_parser.read(config_file, encoding='utf-8')

    return config_parser
